#ifndef __ATCLIENT_H__
#define __ATCLIENT_H__

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#include "gbl_types.h"

#define utlSUCCESS  0
#define utlFAILED  -1


typedef int   utlReturnCode_T, *utlReturnCode_P;

#define RETURNCODE_T utlReturnCode_T

#define TelAtParserID UINT32

typedef enum {
	utlAT_RESULT_CODE_OK           = 0,
	utlAT_RESULT_CODE_CONNECT      = 1,
	utlAT_RESULT_CODE_RING         = 2,
	utlAT_RESULT_CODE_NO_CARRIER   = 3,
	utlAT_RESULT_CODE_ERROR        = 4,
	utlAT_RESULT_CODE_NO_DIAL_TONE = 6,
	utlAT_RESULT_CODE_BUSY         = 7,
	utlAT_RESULT_CODE_NO_ANSWER    = 8,
	utlAT_RESULT_CODE_SUPPRESS     = 100,
	utlAT_RESULT_CODE_NULL
} utlAtResultCode_T;

typedef struct utlAtParser_S *utlAtParser_P;  /* forward declaration */

typedef enum {
    utlAT_DATA_TYPE_DECIMAL,
    utlAT_DATA_TYPE_HEXADECIMAL,
    utlAT_DATA_TYPE_BINARY,
    utlAT_DATA_TYPE_STRING,   /* string double-quotes are optional */
    utlAT_DATA_TYPE_QSTRING,  /* string double-quotes are required */
    utlAT_DATA_TYPE_DIAL_STRING,
} utlAtDataType_T;

typedef union utlAtDataValue_U {
    unsigned int  decimal;
    unsigned int  hexadecimal;
    unsigned int  binary;
    char         *string_p;
    char         *qstring_p;
    char         *dial_string_p;
} utlAtDataValue_T, *utlAtDataValue_P;


typedef enum {
    utlAT_PARAMETER_ACCESS_READ_WRITE,  /* reads and writes  are permitted    */
    utlAT_PARAMETER_ACCESS_READ,        /* attempts to write are ignored      */
    utlAT_PARAMETER_ACCESS_READ_ONLY,   /* attempts to write generates errors */
    utlAT_PARAMETER_ACCESS_WRITE_ONLY   /* attempts to read  generates errors */
} utlAtParameterAccess_T;

/*--- parameter operations ---*/
typedef enum {
    utlAT_PARAMETER_OP_UNKNOWN,
    utlAT_PARAMETER_OP_EXEC,
    utlAT_PARAMETER_OP_GET,
    utlAT_PARAMETER_OP_SET,
    utlAT_PARAMETER_OP_ACTION,
    utlAT_PARAMETER_OP_SYNTAX
} utlAtParameterOp_T, *utlAtParameterOp_P;

typedef struct utlAtParameterValue_S {
    utlAtDataType_T        type;        /* data type of `value' */
    utlAtParameterAccess_T access;
    bool                   is_default;  /* is `value' set to the default value? */
    utlAtDataValue_T       value;       /* parameter's value                    */
}utlAtParameterValue_T, *utlAtParameterValue_P;

typedef const utlAtParameterValue_T  *utlAtParameterValue_P2c;


typedef enum ATCI_RESULT_CODE
{
	ATCI_RESULT_CODE_NULL, //Timer will not stop
	ATCI_RESULT_CODE_OK,   //Timer will stop, OK will be sent
	ATCI_RESULT_CODE_ERROR, //Timer will stop, ERROR will be sent
	ATCI_RESULT_CODE_CME_ERROR, //Timer will Stop, CME ERROR will be sent
	ATCI_RESULT_CODE_CMS_ERROR, //Timer will Stop, CMS ERROR will be sent
	ATCI_RESULT_CODE_SUPPRESS,       //Timer will Stop, End of AT response without OK or ERROR string
	ATCI_RESULT_CODE_CME_ERROR_PROXY,
	ATCI_RESULT_CODE_CMS_ERROR_PROXY,
	ATCI_RESULT_CODE_CMUX_ERROR,
    ATCI_RESULT_CODE_M2M_ERROR,
	ATCI_RESULT_CODE_MAX
}_AtciResultCode;


#define TEL_INVALID_EXT_CMD     utlAT_PARAMETER_OP_UNKNOWN
#define TEL_EXT_EXEC_CMD        utlAT_PARAMETER_OP_EXEC     //AT+CGMI
#define TEL_EXT_GET_CMD         utlAT_PARAMETER_OP_GET      //?
#define TEL_EXT_SET_CMD         utlAT_PARAMETER_OP_SET      //=
#define TEL_EXT_ACTION_CMD      utlAT_PARAMETER_OP_ACTION   //AT+CPAS
#define TEL_EXT_TEST_CMD        utlAT_PARAMETER_OP_SYNTAX   //=?



typedef enum {
    utlAT_COMMAND_TYPE_BASIC,    /* basic AT command              */
    utlAT_COMMAND_TYPE_EXTENDED, /* extended-parameter AT command */
	utlAT_COMMAND_TYPE_EXACTION,     /* extended-action    AT command */
	utlAT_COMMAND_TYPE_EXTENDED_EXACTION, /*extended-parameter & extended-action AT command*/
	utlAT_COMMAND_TYPE_UNKNOWN
} utlAtCommandType_T;


typedef enum {
    utlAT_PARAMETER_PRESENCE_OPTIONAL,  /* parameter presence is optional */
    utlAT_PARAMETER_PRESENCE_REQUIRED,  /* parameter presence is required */
} utlAtParameterPresence_T;

typedef struct utlAtParameter_S {
    utlAtDataType_T          type;  /* parameter's data type */
    utlAtParameterAccess_T   access;
    utlAtParameterPresence_T presence;
}utlAtParameter_T, *utlAtParameter_P;

typedef const utlAtParameter_T  *utlAtParameter_P2c;


/*--- convenience macros ---*/
#define utlDEFINE_BASIC_AT_PARAMETER(type)                    {type, utlAT_PARAMETER_ACCESS_READ_WRITE, utlAT_PARAMETER_PRESENCE_OPTIONAL}
#define utlDEFINE_DECIMAL_AT_PARAMETER(     access, presence) {utlAT_DATA_TYPE_DECIMAL    , access, presence}
#define utlDEFINE_HEXADECIMALL_AT_PARAMETER(access, presence) {utlAT_DATA_TYPE_HEXADECIMAL, access, presence}
#define utlDEFINE_BINARY_AT_PARAMETER(      access, presence) {utlAT_DATA_TYPE_BINARY     , access, presence}
#define utlDEFINE_STRING_AT_PARAMETER(      access, presence) {utlAT_DATA_TYPE_STRING     , access, presence}
#define utlDEFINE_QSTRING_AT_PARAMETER(     access, presence) {utlAT_DATA_TYPE_QSTRING    , access, presence}
#define utlDEFINE_DIAL_STRING_AT_PARAMETER( access, presence) {utlAT_DATA_TYPE_DIAL_STRING, access, presence}

typedef utlReturnCode_T (*utlAtGetParameterFunction_P)      (const utlAtParameterOp_T op, const char *command_name_p, const utlAtParameterValue_P2c parameter_values_p, const size_t num_parameters, const char *info_text_p, unsigned int *xid_p, void *arg_p);
typedef utlReturnCode_T (*utlAtSetParameterFunction_P)      (const utlAtParameterOp_T op, const char *command_name_p, const utlAtParameterValue_P2c parameter_values_p, const size_t num_parameters, const char *info_text_p, unsigned int *xid_p, void *arg_p);
typedef utlReturnCode_T (*utlAtCommandSyntaxFunction_P)     (const utlAtParameterOp_T op, const char *command_name_p, const utlAtParameterValue_P2c parameter_values_p, const size_t num_parameters,const char *info_text_p, unsigned int *xid_p, void *arg_p);



typedef enum
{
    _MAT_MIN = 900,

	_MAT_MAX =  999,    
}MATCmdType, MATRspType;

typedef struct utlAtCommand_S {
	MATCmdType mat_cmd;			 /* MAT command type */
    utlAtCommandType_T  type;    /* AT-Command type */
    const char         *name_p;  /* AT-Command name */

    utlAtParameter_P parameters_p;    /* NULL pointer, or pointer to a variable-length array      */
    size_t           num_parameters;  /* number of elements in array pointed to by `parameters_p' */

    struct {
        const char *command_syntax_p;  /* AT-Command usage string (for syntax queries) */
        struct {
            utlAtCommandSyntaxFunction_P command_syntax_function_p;
        } call_backs;
    } usage;

    struct {
        utlAtGetParameterFunction_P get_parameter_function_p;  /* for get requests          */
        utlAtSetParameterFunction_P set_parameter_function_p;  /* for set & action requests */
    } call_backs;
}utlAtCommand_T, *utlAtCommand_P;

typedef const utlAtCommand_T  *utlAtCommand_P2c;

#define utlDEFINE_EXTENDED_EXACTION_VSYNTAX_AT_COMMAND(mtype, name, parameters_p,   \
        syntax_function_p, get_function_p, action_function_p)   \
        { mtype, utlAT_COMMAND_TYPE_EXTENDED_EXACTION, name, parameters_p,  \
        sizeof(parameters_p) / sizeof(utlAtParameter_T),    \
        { NULL, { syntax_function_p } }, { get_function_p, action_function_p } }


BOOL getExtValue( const utlAtParameterValue_P2c param_value_p,
		int index,
		int *value_p,
		int minValue,
		int maxValue,
		int DefaultValue);

BOOL getExtString ( const utlAtParameterValue_P2c param_value_p,
		int index,
		CHAR *outString,
		INT16 maxStringLength,
		INT16 *outStringLength,
		CHAR *defaultString);

int atRespStr(UINT32 reqHandle, UINT8 resultCode, UINT16 errCode, char *respString);

#define ATRESP(REQHANDLE, RESULTCODE, ERRCODE, RESPSTRING) atRespStr(REQHANDLE, RESULTCODE, ERRCODE, RESPSTRING)


unsigned int atcmds_make_at_handle(unsigned int sAtpIndex);

int atcmds_register(utlAtCommand_T *commands_p, unsigned int num_commands);







/**
* @return       TRUE if AT server is ready.
 */
int at_command_server_ready();

/** indication callback function type */
typedef void (*indcb)(const char *indication);

/**
 * @brief        This function send AT cmd to AT cmd server, and get response, this function is sync call.
 *				 Need to read AT cmd doc before use this API
 *
 * @param[in]    atcmd: AT cmd, must add '\r' at the end of cmd, eg."AT+CPIN?\r"
 * @param[in]    timeout: Timeout in seconds.
 * @param[in]    waitok: if wait "OK" or not
 * 						 1 - the response data will auto return when received 'OK', use for reponse data have 'OK' postfix
 *							 like this:
 *							 AT+CPIN?
 * 						 	 +CPIN: ready
 * 						 	 OK
 * 						 	 AT+CFUN=1
 * 						 	 OK
 *						 0 - the response data will auto return when get response, use for response data have no 'OK' postfix
 * @param[out]   outstr: AT response buffer.
 * @param[in]    outlen: The maximum size of outstr.
 *
 * @return       0 is success or error code otherwise.
 */
int atclient_send(const char *atcmd, int timeout, int waitok, char *outstr, int outlen);

/**
 * @brief        This function set callback function that use to receive indications.
 *
 * @param[in]    callback: function use to receive indications from AT cmd server
 *
 */
void atclient_set_ind_cb(indcb callback);


void atclient_send_ind_data(TelAtParserID sAtpIndex, char* data, int len);

#endif /*__ATCLIENT_H__*/
